import json
import pygame
import random
import os

Path = 'E:\\Environments\\pygame\\fish\\ini.json'
Path1= 'E:\\Environments\\pygame\\fish\\resourcepack\\pixilart.json'
Path2= 'E:\\Environments\\pygame\\fish\\resourcepack\\'

Python_vesion = "3.7.1"
Pygame_SDL_version = f"{pygame.get_sdl_version()[0]}.{pygame.get_sdl_version()[1]}.{pygame.get_sdl_version()[2]}"
stdio: bool = True

difficulty = 0.3
increase_time = 60_000
γ = 6
using_ray_tracing : bool = True
DEBUG : bool = True
render_engine : str = "starlights"
optimize_engine: str= "cesium"
outtextcolor : tuple = (0x8e, 0x8e, 0x6e)
fpslimit: int = 1000
gamemode: str = "easy"
warm_light:int = 7
showTextMax:int = 36
do_ice_spike_hit_fish: bool = True
do_ice_spike_hit_fish_forcelevel: int = 3 # if fish.force <= this, hp->0
ice_spike_yspeed: tuple = (4, 10)
survival_day_mod: int = 1 # if day % this == 0: win or *biome_switch
smoothLight: dict = {
    "open": True,
    "max":  False
}
mob:dict = {}
biome:dict = {}
biomefilter:dict = {}
version:dict = {}

class MissingResourceError(Exception):
    def __init__(self, value) -> None:
        self.value = value
    def __str__(self) -> str:
        return repr(self.value)

def reload():
    global difficulty, increase_time, γ, using_ray_tracing, DEBUG, render_engine, outtextcolor, mob, biome, fpslimit, gamemode, biomefilter, version
    global optimize_engine, warm_light
    with open(Path, 'r', encoding = 'UTF-8') as f:
        data = json.load(f)
        if type(data['difficulty']) is not float:
            raise TypeError(f'Error in ini.json: difficulty must be float, not {type(data["difficulty"])}')
        difficulty = data['difficulty']
        #increase_time = data['Increase_diff_time']
        if type(data['gamma']) is not int:
            raise TypeError(f'Error in ini.json: gamma must be int, not {type(data["gamma"])}')
        γ = data['gamma']
        if type(data['using_ray_tracing']) != bool:
            raise TypeError(f'Error in ini.json: using_ray_tracing must be bool, not {type(data["using_ray_tracing"])}')
        using_ray_tracing = data['using_ray_tracing']
        if type(data['DEBUG']) != bool:
            raise TypeError(f'Error in ini.json: DEBUG must be bool, not {type(data["DEBUG"])}')
        DEBUG = data['DEBUG']
        if type(data['rendering_engine']) != str:
            raise TypeError(f'Error in ini.json: DEBUG must be bool, not {type(data["rendering_engine"])}')
        if data['rendering_engine'] not in ("starlights", "strontium"):
            raise ValueError(f'Error in ini.json: render engine must be "starlights" or "strontium", not {data["rendering_engine"]}')
        render_engine = data['rendering_engine']
        if type(data['outtextcolor']) != list:
            raise TypeError(f'Error in ini.json: outtextcolor must be list, not {type(data["outtextcolor"])}')
        outtextcolor = data['outtextcolor']

        if type(data['fpslimit']) != int:
            raise TypeError(f'Error in ini.json: fpslimit must be int, not {type(data["fpslimit"])}')
        if 20 < data['fpslimit'] <= 1024:
            fpslimit = data['fpslimit']
        if data['gamemode'] not in ('easy', 'hard'):
            raise ValueError(f'Error in ini.json: gamemode must in ["easy", "hard"], not {data["gamemode"]}')
        gamemode = data["gamemode"]

        if type(data['mob']) != dict:
            raise TypeError(f'Error in ini.json: mob must be dict, not {type(data["mob"])}')
        for k in ('small', 'mid', 'large', 'lantern', 'shark', 'su'):
            if k not in data['mob']:
                raise KeyError(f'Error in ini.json::mob: except key "{k}" in dict')
            if type(data['mob'][k]['speed']) != list or len(data['mob'][k]['speed']) != 2:
                raise ValueError(f'Error in ini.json::mob::{k}::speed: speed must be a list with length "2"')
            if k == 'lantern':
                if len(data['mob']['lantern']['light_block_value']) != 2:
                    raise ValueError('Error in ini.json::mob::lantern::light_block_value: light must be a list with length "2"')
        mob = data['mob']
        ...
        if type(data['biome']) != dict:
            raise TypeError(f'Error in ini.json: biome must be dict, not {type(data["biome"])}')
        biome = data['biome']
        if type(data['biome_filter']) != dict:
            raise TypeError(f'Error in ini.json: biome_filter must be dict, not {type(data["biome_filter"])}')
        biomefilter = data['biome_filter']
        if type(data['version']) != dict:
            raise TypeError(f'Error in ini.json: version must be dict, not {type(data["version"])}')
        version = data['version']
        if data['optimize_engine'] not in ("cesium", "rubidium"):
            raise ValueError(f'Error in ini.json: optimize engine must be "cesium" or "rubidium", not {data["optimize_engine"]}')
        optimize_engine = data['optimize_engine']

        if type(data['warm_light']) != int:
            raise TypeError(f'Error in ini.json: warm_light must be int, not {type(data["warm_light"])}')
        if 1 < data['warm_light'] <= 10:
            warm_light = data['warm_light']
    return

bgs = [] # background
grass_safes = []
sea_urchin = []
player_s_l : pygame.surface.Surface
player_m_l : pygame.surface.Surface
player_l_l : pygame.surface.Surface
player_s_r : pygame.surface.Surface
player_m_r : pygame.surface.Surface
player_l_r : pygame.surface.Surface
player_hx_s : int
player_hy_s : int
player_hx_m : int
player_hy_m : int
player_hx_l : int
player_hy_l : int
small_fishes = []
middle_fishes = []
large_fishes = []
lantern_fishes = []
shark_fishes = []

def cint(d) -> int:
    return d if type(d) is int else int(d)

def prob(p : int) -> bool:
    if random.randint(0, 100) < p:
        return True
    return False

class small(object):
    def __init__(self, pic : str, smart : int = 0) -> None:
        self.img = pygame.image.load(Path2 + pic).convert()
        self.img.set_colorkey((255, 255, 255))
        pixiv = ((pic.split('.')[0]).split('_')[-1]).split('-')
        pixiv_x, pixiv_y = cint(pixiv[0]), cint(pixiv[1])
        xset = random.randint(46, 56)
        pixiv_y = cint(pixiv_y * xset / pixiv_x )
        pixiv_x = xset
        self.img = pygame.transform.scale(self.img, (pixiv_x, pixiv_y))
        self.imgl, self.imgr = None, None
        if pic.split('_')[3] in ('l', 'L', 'left', 'Left'):
            self.imgl = self.img
            self.imgr = pygame.transform.flip(self.img, True, False)
        else:
            self.imgr = self.img
            self.imgl = pygame.transform.flip(self.img, True, False)
        self.dtype = 'small'
        self.hx = cint(xset / 2)
        self.hy = cint(pixiv_y / 2)
        self.x, self.y = 0, 0
        if prob(50):
            self.x = random.randint(1800, 1920)
        else:
            self.x = random.randint(-380, -220)
        if smart == 0:
            self.y = random.randint(50, 920)
        else:
            self.y = random.randint(-200, 1080)
        self.smart = smart
        self.speed = random.randint(3, 18)

class middle(object):
    def __init__(self, pic : str, smart : int = 0) -> None:
        self.img = pygame.image.load(Path2 + pic).convert()
        self.img.set_colorkey((255, 255, 255))
        pixiv = ((pic.split('.')[0]).split('_')[-1]).split('-')
        pixiv_x, pixiv_y = cint(pixiv[0]), cint(pixiv[1])
        xset = random.randint(88, 118)
        pixiv_y = cint(pixiv_y * xset / pixiv_x )
        pixiv_x = xset
        self.img = pygame.transform.scale(self.img, (pixiv_x, pixiv_y))
        self.imgl, self.imgr = None, None
        if pic.split('_')[3] in ('l', 'L', 'left', 'Left'):
            self.imgl = self.img
            self.imgr = pygame.transform.flip(self.img, True, False)
        else:
            self.imgr = self.img
            self.imgl = pygame.transform.flip(self.img, True, False)
        self.dtype = 'small'
        self.hx = cint(xset / 2)
        self.hy = cint(pixiv_y / 2)
        self.x, self.y = 0, 0
        if prob(50):
            self.x = random.randint(1800, 1920)
        else:
            self.x = random.randint(-380, -220)
        if smart == 0:
            self.y = random.randint(50, 920)
        else:
            self.y = random.randint(-200, 1080)
        self.smart = smart
        self.speed = random.randint(3, 18)

class large(object):
    def __init__(self, pic : str, smart : int = 0) -> None:
        self.img = pygame.image.load(Path2 + pic).convert()
        self.img.set_colorkey((255, 255, 255))
        pixiv = ((pic.split('.')[0]).split('_')[-1]).split('-')
        pixiv_x, pixiv_y = cint(pixiv[0]), cint(pixiv[1])
        xset = random.randint(128, 156)
        pixiv_y = cint(pixiv_y * xset / pixiv_x )
        pixiv_x = xset
        self.img = pygame.transform.scale(self.img, (pixiv_x, pixiv_y))
        self.imgl, self.imgr = None, None
        if pic.split('_')[3] in ('l', 'L', 'left', 'Left'):
            self.imgl = self.img
            self.imgr = pygame.transform.flip(self.img, True, False)
        else:
            self.imgr = self.img
            self.imgl = pygame.transform.flip(self.img, True, False)
        self.dtype = 'small'
        self.hx = cint(xset / 2)
        self.hy = cint(pixiv_y / 2)
        self.x, self.y = 0, 0
        if prob(50):
            self.x = random.randint(1800, 1920)
        else:
            self.x = random.randint(-380, -220)
        if smart == 0:
            self.y = random.randint(50, 920)
        else:
            self.y = random.randint(-200, 1080)
        self.smart = smart
        self.speed = random.randint(3, 18)

class lanternfish(object):
    def __init__(self, pic : str, smart : int = 0) -> None:
        self.img = pygame.image.load(Path2 + pic).convert()
        self.img.set_colorkey((255, 255, 255))
        pixiv = ((pic.split('.')[0]).split('_')[-1]).split('-')
        pixiv_x, pixiv_y = cint(pixiv[0]), cint(pixiv[1])
        xset = 26 # random.randint(26, 190)
        pixiv_y = cint(pixiv_y * xset / pixiv_x )
        pixiv_x = xset
        self.img = pygame.transform.smoothscale(self.img, (pixiv_x, pixiv_y))
        self.imgl, self.imgr = None, None
        if pic.split('_')[3] in ('l', 'L', 'left', 'Left'):
            self.imgl = self.img
            self.imgr = pygame.transform.flip(self.img, True, False)
        else:
            self.imgr = self.img
            self.imgl = pygame.transform.flip(self.img, True, False)
        self.dtype = 'lanternfish'
        self.hx = cint(xset / 2)
        self.hy = cint(pixiv_y / 2)
        self.x, self.y = 0, 0
        if prob(50):
            self.x = random.randint(1800, 1920)
        else:
            self.x = random.randint(-380, -220)
        if smart == 0:
            self.y = random.randint(50, 920)
        else:
            self.y = random.randint(-200, 1080)
        self.smart = smart
        self.speed = random.randint(3, 18)

class SHArk(object):
    def __init__(self, pic : str, smart : int = 0) -> None:
        self.img = pygame.image.load(Path2 + pic).convert()
        self.img.set_colorkey((255, 255, 255))
        pixiv = ((pic.split('.')[0]).split('_')[-1]).split('-')
        pixiv_x, pixiv_y = cint(pixiv[0]), cint(pixiv[1])
        xset = random.randint(221, 376)
        pixiv_y = cint(pixiv_y * xset / pixiv_x )
        pixiv_x = xset
        self.img = pygame.transform.scale(self.img, (pixiv_x, pixiv_y))
        self.imgl, self.imgr = None, None
        if pic.split('_')[3] in ('l', 'L', 'left', 'Left'):
            self.imgl = self.img
            self.imgr = pygame.transform.flip(self.img, True, False)
        else:
            self.imgr = self.img
            self.imgl = pygame.transform.flip(self.img, True, False)
        self.dtype = 'small'
        self.hx = cint(xset / 2)
        self.hy = cint(pixiv_y / 2)
        self.x, self.y = 0, 0
        if prob(50):
            self.x = random.randint(1800, 1920)
        else:
            self.x = random.randint(-380, -220)
        if smart == 0:
            self.y = random.randint(50, 920)
        else:
            self.y = random.randint(-200, 1080)
        self.smart = smart
        self.speed = random.randint(3, 18)

def Reload():
    global player_l_l, player_m_l, player_s_l, player_l_r, player_m_r, player_s_r
    global player_hy_l, player_hx_l, player_hx_m, player_hy_m, player_hx_s, player_hy_s
    flist = os.listdir(Path2)
    for f in flist:
        if '_' not in f or '.' not in f:
            continue
        dat = (f.split('.')[0]).split('_')
        if len(dat) != 5:
            if len(dat) == 2 and dat[0] == 'background':
                bg = pygame.image.load(Path2 + f).convert()
                bg = pygame.transform.scale(bg, (1650, 920))
                white = pygame.Surface((1650, 920))
                white.fill((20, 20, 20))
                bg.blit(white, (0, 0), special_flags=pygame.BLEND_RGB_ADD)
                bgs.append(bg)
                continue
            elif len(dat) == 2 and dat[0] == 'grasssafe':
                gs = pygame.image.load(Path2 + f).convert()
                gs = pygame.transform.scale(gs, (130, 160))
                gs.set_colorkey((255, 255, 255))
                white = pygame.Surface((130, 160))
                white.fill((20, 20, 20))
                gs.blit(white, (0, 0), special_flags=pygame.BLEND_RGB_ADD)
                grass_safes.append(gs)
                continue
            elif len(dat) == 2 and dat[0] == 'seaurchin':
                su = pygame.image.load(Path2 + f).convert()
                #su = pygame.transform.scale(su, (130, 160))
                su.set_alpha(128)
                su.set_colorkey((255, 255, 255))
                sea_urchin.append(su)
                continue
            elif len(dat) == 3 and dat[0] == 'player':
                p = pygame.image.load(Path2 + f).convert()
                p.set_colorkey((255, 255, 255))
                pixiv = dat[2].split('-')
                if dat[1] == 's':
                    pixiv_x, pixiv_y = cint(pixiv[0]), cint(pixiv[1])
                    xset = random.randint(46, 56)
                    pixiv_y = cint(pixiv_y * xset / pixiv_x )
                    pixiv_x = xset
                    player_s_l = pygame.transform.scale(p, (pixiv_x, pixiv_y))
                    player_s_r = pygame.transform.flip(player_s_l, True, False)
                    player_hx_s = cint(xset / 2)
                    player_hy_s = cint(pixiv_y / 2)
                elif dat[1] == 'm':
                    pixiv_x, pixiv_y = cint(pixiv[0]), cint(pixiv[1])
                    xset = random.randint(90, 110)
                    pixiv_y = cint(pixiv_y * xset / pixiv_x )
                    pixiv_x = xset
                    player_m_l = pygame.transform.scale(p, (pixiv_x, pixiv_y))
                    player_m_r = pygame.transform.flip(player_m_l, True, False)
                    player_hx_m = cint(xset / 2)
                    player_hy_m = cint(pixiv_y / 2)
                elif dat[1] == 'l':
                    pixiv_x, pixiv_y = cint(pixiv[0]), cint(pixiv[1])
                    xset = random.randint(140, 160)
                    pixiv_y = cint(pixiv_y * xset / pixiv_x )
                    pixiv_x = xset
                    player_l_l = pygame.transform.scale(p, (pixiv_x, pixiv_y))
                    player_l_r = pygame.transform.flip(player_l_l, True, False)
                    player_hx_l = cint(xset / 2)
                    player_hy_l = cint(pixiv_y / 2)
                else:
                    pass
                continue
            else:
                continue
        size, largenum, imgindex, way, pixivdata = dat[0], dat[1], dat[2], dat[3], dat[4]
        if way not in ('l','L','left','Left','r','R','right','Right'):
            continue
        if size in ('s','S','small','Small'):
            obj = small(f, random.randint(0, 2))
            small_fishes.append(obj)
        elif size in ('m', 'M', 'Middle','middle','midium'):
            obj = middle(f, random.randint(0, 2))
            middle_fishes.append(obj)
        elif size in ('l', 'L', 'large', 'Large'):
            obj = large(f, random.randint(0, 2))
            large_fishes.append(obj)
        elif size in ('lantern', 'Lantern', 'lanternfish', 'Lanternfish', 'lantern_fish', 'lanternFish'):
            obj = lanternfish(f, random.randint(0, 2))
            lantern_fishes.append(obj)
        elif size in ('Shark_fish', 'shark_fish', 'SharkFish','shark', 'Shark'):
            obj = SHArk(f, random.randint(0, 2))
            shark_fishes.append(obj)
        else:
            pass
    if [] in [small_fishes, middle_fishes, large_fishes, bgs, grass_safes, lantern_fishes, shark_fishes, sea_urchin]:
        raise MissingResourceError('Missing resource: fishpics')
    
screen : pygame.surface.Surface
fps : pygame.time.Clock
Error_Message = None
main_isend : bool = False
graphic_isend :bool = False

def init(scr: pygame.surface.Surface, FPS : pygame.time.Clock):
    global screen, fps
    screen = scr
    fps = FPS
    reload()
    Reload()

def AtExit():
    os.system('pause')

def set_settings():
    while True:
        fps.tick(10)
        screen.fill((200, 255, 220))
        # display, texins
        pygame.display.flip()

def home():
    ...